import tkinter as tk
from tkinter import ttk
from PIL import Image, ImageTk
from functools import partial
import json

class Calculation:
    def __init__(self, root, config_file_path):
        with open(config_file_path, 'r', encoding='utf-8') as config_file:
            config = json.load(config_file)

        self.images = config["images"]
        self.names = config["names"]
        self.operators = config["operators"]
        self.base_values = config["base_values"]
        self.increment_values = config["increment_values"]
        self.initial_value = config["initial_value"]

        # 操作历史 [{idx: , 连续数量: , 总共数量: }]
        #  {'idx':3,'count':2,'count_sum':5}
        self.history_dicts = []
        # 计算式列表 [' + 名(值)', ' - 名*数量(值+值)']
        self.op_strs = []
        self.v_entry = tk.StringVar()

        self.root = root
        self.root.title("BoomBeach能量演算")

        # 设置窗口最小尺寸
        # self.root.minsize(500, 200)
        self.root.resizable(False, False)

        # 创建一个容器来放置图片,并设置padding
        self.container = ttk.Frame(self.root)
        self.container.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=20, 
            pady=(10, 3))

        # 输入框容器
        self.container_entry = ttk.Frame(self.root)
        self.container_entry.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=20, 
            pady=(2, 2))
        # self.container_entry.pack_propagate(0)
        # 计算式容器
        self.container_label = ttk.Frame(self.root)
        self.container_label.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=20, 
            pady=(1, 10))

        # 创建图片和按钮
        for idx, (image, base_value, increment_value, name, operator) in enumerate(
            zip(self.images, self.base_values, self.increment_values, self.names, self.operators)):
            self.create_image_and_buttons(idx, image, base_value, 
                increment_value, name, operator)

        # 创建输入框及其标签
        self.label = ttk.Label(self.container_entry, text="初始能量:", font=("TkDefaultFont", 12))
        self.label.grid(row=3, column=1, columnspan=2, sticky=tk.EW, padx=2)
        self.entry = ttk.Entry(self.container_entry, textvariable=self.v_entry)
        self.entry.grid(row=3, column=3, columnspan=2, sticky=tk.EW, padx=2)
        # self.entry.insert(tk.END, str(initial_value))
        self.v_entry.set(str(self.initial_value))
        # 配置验证
        vcmd = (self.root.register(partial(self.validate_input, self.container_entry)), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
        self.entry.config(validate='key', validatecommand=vcmd)

        # 创建 "上一步" 按钮
        undo_button = ttk.Button(self.container_entry, text="上一步", 
             command=self.undo_last_operation)
        undo_button.grid(row=3, column=5, sticky=tk.EW, padx=(10,2))

        # 创建 "清除" 按钮
        clear_button = ttk.Button(self.container_entry, text="重置", 
            command=self.clear_all)
        clear_button.grid(row=3, column=6, sticky=tk.EW, padx=2)

        # 创建一个标签用于显示计算式
        self.operation_label = ttk.Label(self.container_label, text=f"{self.initial_value}")
        self.operation_label.grid(row=0, column=0, sticky=tk.NSEW)

        self.root.update()
        self.operation_label.config(wraplength=self.container_label.winfo_width()-10)

    def create_image_and_buttons(self, idx, image, base_value, 
        increment_value, name, operator):
        # 加载图片
        img = Image.open(image)
        # 调整图片大小
        # img.thumbnail((60, 60), Image.LANCZOS)
        img = img.resize((60,60))
        photo = ImageTk.PhotoImage(img)

        # 创建图片标签
        label = ttk.Label(self.container, image=photo)
        label.image = photo  # 保持对图像的引用
        rid = int(idx/8)
        cid = idx*2 - rid*16
        label.grid(row=rid, column=cid, columnspan=2, sticky=tk.NSEW)
        # 绑定点击事件
        label.bind("<Button-1>", lambda event, idx=idx, base_value=base_value, 
            increment_value=increment_value, 
            name=name, operator=operator: self.on_image_click(
                event, idx)
            )

    def on_image_click(self, event, idx):
        # 处理图片点击事件
        self.add_history(idx)
        self.update_operation()
        
    # 保存到历史记录
    def add_history(self, idx):
        count = 1
        count_sum = 1
        if len(self.history_dicts) > 0 and self.history_dicts[-1]['idx'] == idx:
            count = self.history_dicts[-1]['count'] + 1
        for dic in self.history_dicts[::-1]:
            if dic['idx'] == idx:
                count_sum = dic['count_sum'] + 1
                break

        self.history_dicts.append({'idx':idx,'count':count,'count_sum':count_sum})

    # 更新显示的计算式
    #  0 - 多管 (10) - 炸弹 * 2 (3 + 5) - 多管 * 2 (16 + 22) = -56
    def update_operation(self):
        displayed_operation = f"{self.entry.get()}"
        # 计算式列表 [' + 名(值)', ' - 名*数量(值+值)']
        self.op_strs = []
        self.initial_value = int(self.entry.get())
        sum_value = int(self.entry.get())
        for i, history in enumerate(self.history_dicts):
            idx = history['idx']
            base_value = int(self.base_values[idx])
            increment_value = int(self.increment_values[idx])
            operator = self.operators[idx]
            name = self.names[idx]
            count = history['count']
            count_sum = history['count_sum']
            value_last = int(base_value + (count_sum - 1) * increment_value)

            values = []
            values_str = ''
            if count > 1 :
                for c in range(count, 0, -1):
                    # values.append(value_last - (c - 1) * increment_value)
                    values.append(f"{value_last - (c - 1) * increment_value}")
                # values_str = ' + '.join(str(value) for value in values)
                values_str = ' + '.join(values)
                del self.op_strs[-1]
                self.op_strs.append(f"{operator} {name} * {count} ({values_str})")

            else:
                self.op_strs.append(f"{operator} {name} ({value_last})")

            if operator == '+':
                sum_value += value_last
            if operator == '-':
                sum_value -= value_last

        displayed_operation += ' '.join(self.op_strs)

        # 更新界面上的显示
        # 添加等于号和计算结果
        displayed_operation += f" = {sum_value}"
        self.operation_label.config(text=displayed_operation)

    def undo_last_operation(self):
        if self.history_dicts:
            self.history_dicts.pop()
            self.update_operation()
    
    def clear_all(self):
        self.history_dicts.clear()
        self.update_operation()

    # 验证输入框的值
    def validate_input(self, root, action, index, value_if_allowed, prior_value, 
                    text, validation_type, trigger_type, widget_name):
        """ 验证输入是否在 0 到 100 之间 """
        if value_if_allowed.isdigit() and 0 <= int(value_if_allowed) <= 100000:
            if int(value_if_allowed) >= 1000:
                self.v_entry.set(value_if_allowed[0:4])
            return True
        elif value_if_allowed == "":  # 允许空字符串
            self.v_entry.set(prior_value)
            return True
        else:
            return False

# 创建主窗口
root = tk.Tk()

# 指定配置文件路径
config_file_path = "boombeach_config.json"

app = Calculation(root, config_file_path)

# 启动事件循环
root.mainloop()